package com.xmut.mall.order.service.impl;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xmut.mall.order.dto.PriceDetailDTO;
import com.xmut.mall.order.entity.*;
import com.xmut.mall.order.feign.ProductFeignService;
import com.xmut.mall.order.feign.StoreFeignService;
import com.xmut.mall.order.feign.WareFeignService;
import com.xmut.mall.order.myenum.*;
import com.xmut.mall.order.myexpection.WareReduceFailException;
import com.xmut.mall.order.searchparam.ManagerOrderSearchParam;
import com.xmut.mall.order.searchparam.OrderSearchParams;
import com.xmut.mall.order.searchparam.SellerOrderSearchParam;
import com.xmut.mall.order.service.OrderItemService;
import com.xmut.mall.order.service.OrderLogService;
import com.xmut.mall.order.service.TradeService;
import com.xmut.mall.order.to.CreateOrderDto;
import com.xmut.mall.order.to.LogisticsEntityDto;
import com.xmut.mall.order.to.OrderDeliveryDto;
import com.xmut.mall.order.to.UpdateOrderConsigneeDto;
import com.xmut.mall.order.utils.CurrencyUtil;
import com.xmut.mall.order.utils.PageUtil;
import com.xmut.mall.order.utils.RespBean;
import com.xmut.mall.order.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.mall.order.dao.OrderDao;
import com.xmut.mall.order.service.OrderService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


@Slf4j
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private OrderLogService orderLogService;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private TradeService tradeService;

    @Autowired
    private StoreFeignService storeFeignService;

    /**
     * 保存订单
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean createOrder(OrderEntity entity) {
        // RocketMQ发送定时消息
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(sra, true);
        DefaultMQProducer producer = new DefaultMQProducer("ordergroup");
        producer.setNamesrvAddr("192.168.253.128:9876");
        try {
            producer.start();
            Message message = new Message();
            // 设置map参数
            Map<String, Object> params = new HashMap<>();
            params.put("orderSN", entity.getSn());
            message.setBody(JSON.toJSONString(params).getBytes(StandardCharsets.UTF_8));
            message.setTopic("OrderLockStockTopic");
            message.setDelayTimeLevel(5); // 实验环境默认给1分钟取消订单
            SendResult send = producer.send(message);
            System.out.println("Rocketmq发送结果:" + send.getSendStatus());
        } catch (MQClientException e) {
            e.printStackTrace();
        } catch (MQBrokerException e) {
            e.printStackTrace();
        } catch (RemotingException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                producer.shutdown();
                System.out.println("链接已关闭");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 保存订单
        entity.setOrderStatus(OrderStatusEnum.UNPAID.description()); // 前面的核验都已完成 这里修改状态为未付款
        boolean save = this.save(entity);
        if (save) {
            return RespBean.success("保存成功");
        } else {
            return RespBean.error("保存失败");
        }
    }

    /**
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelOrderReasonTimeout(Map<String, Object> param) {
        String orderSN = MapUtil.getStr(param, "orderSN");
        String reason = MapUtil.getStr(param, "Reason");// 订单取消原因
        OrderEntity order = getOrderBySn(orderSN);
        // 前置判断 如果订单状态不是未支付 这里的就全部停止
        if (!order.getPayStatus().equals("待付款")){
            return;
        }
        // 获取当前订单 拿到trade_sn 修改当前交易信息为已取消
        tradeService.update(new UpdateWrapper<TradeEntity>()
                .set("pay_status", PayStatusEnum.CANCEL.description())
                .eq("sn", order.getTradeSn()));

        // 修改订单信息
        this.update(new UpdateWrapper<OrderEntity>()
                .set("cancel_reason", reason)
                .set("order_status", OrderStatusEnum.CANCELLED.description())
                .set("pay_status", PayStatusEnum.CANCEL.description())
                .eq("sn", orderSN));

        // 保存日志信息
        OrderLogEntity orderLogEntity = new OrderLogEntity();
        orderLogEntity.setOrderSn(orderSN);
        String message = "订单[" + orderSN + "]因超时取消";
        orderLogEntity.setMessage(message);
        orderLogEntity.setOperatorType(UserEnums.SYSTEM.getRole());
        orderLogEntity.setOperatorId(0l);
        orderLogEntity.setOperatorName(UserEnums.SYSTEM.getRole());
        orderLogEntity.setCreateTime(new Date());
        // 保存订单日志
        orderLogService.save(orderLogEntity);

    }

    /**
     * 收到MQ消息之后创建订单和订单项
     *
     * @param param
     */
    @Override
    public void MQCreateOrder(Map<String, Object> param) {
        String tradeSN = MapUtil.getStr(param, "tradeSN");// 交易单号
        Map<Long, CreateOrderDto> createOrderIds = MapUtil.get(param, "createOrderIds", new TypeReference<Map<Long, CreateOrderDto>>() {
        });
        MemberReceiveAddressEntityVo address = MapUtil.get(param, "address", MemberReceiveAddressEntityVo.class);
        Long userId = MapUtil.getLong(param, "userId");
        String userName = MapUtil.getStr(param, "userName");
        List<remarkVo> remark = MapUtil.get(param, "remark", new TypeReference<List<remarkVo>>() {
        });
        List<MemberCartEntityVo> memberCartEntityList = MapUtil.get(param, "memberCartEntityList", new TypeReference<List<MemberCartEntityVo>>() {
        });
        BigDecimal everyItemFullDiscountReduce = MapUtil.get(param, "everyItemFullDiscountReduce", BigDecimal.class);
        BigDecimal everyItemCouponReduce = MapUtil.get(param, "everyItemCouponReduce", BigDecimal.class);
        String usePlatformMemberCouponIds = MapUtil.getStr(param, "usePlatformMemberCouponIds");
        String useStoreMemberCouponIds = MapUtil.getStr(param, "useStoreMemberCouponIds");
        PriceDetailDTO priceDetailDTO = MapUtil.get(param, "priceDetailDTO", PriceDetailDTO.class);

        // 创建交易号
        TradeEntity tradeEntity = new TradeEntity();
        tradeEntity.setConsigneeName(address.getName());
        tradeEntity.setConsigneeAddressIdPath(address.getConsigneeAddressIdPath());
        tradeEntity.setConsigneeAddressPath(address.getConsigneeAddressPath());
        // 优惠的价格 优惠券减掉的价格 + 满减减掉的价格
        BigDecimal discountPrice = priceDetailDTO.getCouponPrice().add(priceDetailDTO.getDiscountPrice());
        tradeEntity.setDiscountPrice(discountPrice);
        tradeEntity.setFlowPrice(priceDetailDTO.getFlowPrice()); // 总价
        tradeEntity.setFreightPrice(priceDetailDTO.getFreightPrice()); // 运费
        tradeEntity.setGoodsPrice(priceDetailDTO.getOriginalPrice()); // 原价
        tradeEntity.setMemberId(userId);
        tradeEntity.setMemberName(userName);
        tradeEntity.setSn(tradeSN);// 交易单号唯一SN码
        tradeEntity.setDeliveryMethod(DeliveryMethodEnum.LOGISTICS.getDescription()); // 配送方式(默认物流)
        tradeEntity.setConsigneeMobile(address.getMobile()); // 收货人手机号码
        tradeEntity.setPayStatus(PayStatusEnum.UNPAID.description()); // 付款状态 未付款
        tradeEntity.setCreateTime(new Date());
        tradeService.save(tradeEntity); // 保存交易订单

        // 获取去重的商品iD
        List<Long> storeIds = memberCartEntityList.stream().map(MemberCartEntityVo::getStoreId).distinct().collect(Collectors.toList());
        for (Long storeId : storeIds) {
            CreateOrderDto createOrderDto = createOrderIds.get(storeId);
            // 生成订单
            OrderEntity orderEntity = new OrderEntity();
            List<OrderItemEntity> orderItemList = new ArrayList<>();
            // 计算价格(此处是大订单的价格 并非订单项)
            PriceDetailDTO orderPriceDetailDto = new PriceDetailDTO();
            orderPriceDetailDto.setFreightPrice(BigDecimal.ZERO);
            BigDecimal orderDiscountPrice = BigDecimal.ZERO;
            BigDecimal orderCouponPrice = BigDecimal.ZERO;
            BigDecimal orderOriginalPrice = BigDecimal.ZERO;// 订单现在的总价格
            Date ORDERCREATE = new Date();
            // set总订单数据
            orderEntity.setSn(createOrderDto.getOrderSN());
            orderEntity.setTradeSn(tradeSN); // 交易号码
            orderEntity.setCreateTime(ORDERCREATE);
            orderEntity.setCanReturn(true); // 目前该功能未做 先默认全部可以退货
            orderEntity.setClientType(ClientTypeEnum.PC.value());
            // 总订单地址信息
            orderEntity.setConsigneeAddressIdPath(address.getConsigneeAddressIdPath());
            orderEntity.setConsigneeAddressPath(address.getConsigneeAddressPath());
            orderEntity.setConsigneeDetail(address.getDetail());
            orderEntity.setConsigneeMobile(address.getMobile());
            orderEntity.setConsigneeName(address.getName());
            orderEntity.setDeliverStatus(DeliverStatusEnum.UNDELIVERED.getDescription()); // 发货状态
            orderEntity.setDeliveryMethod(DeliveryMethodEnum.LOGISTICS.getDescription());
            orderEntity.setMemberId(userId);
            orderEntity.setMemberName(userName);
            orderEntity.setNeedReceipt(false); // 发票系统还未开发 暂时先给false 不需要
            orderEntity.setOrderStatus(OrderStatusEnum.TAKE.description());
            orderEntity.setOrderType(OrderTypeEnum.NORMAL.name());
            orderEntity.setPayStatus(PayStatusEnum.UNPAID.description());
            // 设置用户订单备注
            for (remarkVo remarkVo : remark) {
                if (storeId.equals(remarkVo.getStoreId())) {
                    orderEntity.setRemark(remarkVo.getRemark());
                }
            }
            Long orderTotalNum = new Long(0);
            // 订单按照不同的店铺来分 同一个店铺下的不同商品就变成订单项
            for (Long skuId : createOrderDto.getSkuIds()) {
                // 订单里面包含的订单项
                MemberCartEntityVo memberCartEntityVo = getCartSkuItem(memberCartEntityList, skuId);// 根据skuId 获取memberCartEntityList对应的sku
                RespBean getSpuInfoBySpuIdResp = productFeignService.getSpuInfoBySpuId(memberCartEntityVo.getSpuId());
                SpuInfoEntityVo spu = JSON.parseObject(JSON.toJSONString(getSpuInfoBySpuIdResp.getObj()), SpuInfoEntityVo.class);
                /**
                 * 此处在计算总订单并非订单项
                 *
                 * 订单当前满减price = 每个订单项分担的满减价格 * 商品数量
                 * 订单当前的优惠券减价 = 每个订单项分担的优惠券减价价格 * 商品数量
                 */
                orderTotalNum += memberCartEntityVo.getProductCount();
                orderDiscountPrice = everyItemFullDiscountReduce
                        .multiply(new BigDecimal(orderTotalNum));
                orderCouponPrice = everyItemCouponReduce
                        .multiply(new BigDecimal(orderTotalNum));
                orderOriginalPrice = orderOriginalPrice.add(memberCartEntityVo.getSkuPrice());
                orderEntity.setStoreId(memberCartEntityVo.getStoreId());
                orderEntity.setStoreName(memberCartEntityVo.getStoreName());
                orderEntity.setWeight(spu.getWeight()
                        .multiply(new BigDecimal(memberCartEntityVo.getProductCount().toString())));
                // 计算该订单项的小计
                PriceDetailDTO orderItemPriceDetailDto = new PriceDetailDTO();
                BigDecimal orderItemOriginalPrice = memberCartEntityVo.getSkuPrice();
                orderItemPriceDetailDto.setOriginalPrice(orderItemOriginalPrice);
                orderItemPriceDetailDto.setGoodsPrice(orderItemOriginalPrice);
                orderItemPriceDetailDto.setFreightPrice(BigDecimal.ZERO);
                orderItemPriceDetailDto.setDiscountPrice(everyItemFullDiscountReduce);
                orderItemPriceDetailDto.setCouponPrice(everyItemCouponReduce);
                BigDecimal orderItemFlowPrice = orderItemOriginalPrice
                        .subtract(everyItemFullDiscountReduce)
                        .subtract(everyItemCouponReduce);
                orderItemPriceDetailDto.setFlowPrice(orderItemFlowPrice);
                orderItemPriceDetailDto.setBillPrice(orderItemFlowPrice);
                orderItemPriceDetailDto.setTotalNum(memberCartEntityVo.getProductCount());
                /**
                 * 生成订单项 orderItem
                 */
                OrderItemEntity orderItemEntityVo = new OrderItemEntity();
                String orderItemSn = "OI"+ IdWorker.getTimeId();
                orderItemEntityVo.setCreateTime(ORDERCREATE);
                orderItemEntityVo.setCategoryId(memberCartEntityVo.getCatalogId());
                orderItemEntityVo.setFlowPrice(memberCartEntityVo.getSkuPrice()
                        .subtract(everyItemCouponReduce)
                        .subtract(everyItemFullDiscountReduce));
                orderItemEntityVo.setGoodsPrice(orderItemPriceDetailDto.getOriginalPrice());
                orderItemEntityVo.setGoodsId(memberCartEntityVo.getSkuId());
                orderItemEntityVo.setImage(memberCartEntityVo.getSkuImg());
                orderItemEntityVo.setGoodsName(memberCartEntityVo.getSkuName());
                orderItemEntityVo.setNum(Integer.parseInt(memberCartEntityVo.getProductCount().toString()));
                orderItemEntityVo.setOrderSn(createOrderDto.getOrderSN());
                orderItemEntityVo.setSn(orderItemSn); // 订单单独的SN
                orderItemEntityVo.setPriceDetail(JSON.toJSONString(orderItemPriceDetailDto));
                orderItemEntityVo.setPromotionType(OrderPromotionTypeEnum.NORMAL.name());
                orderItemEntityVo.setSkuId(memberCartEntityVo.getSkuId());
                //                orderItemEntityVo.setSpecs(); // 规格Id 暂时不搞
                orderItemEntityVo.setUnitPrice(memberCartEntityVo.getSkuPrice());
                orderItemEntityVo.setSubTotal(memberCartEntityVo.getSkuPrice()
                        .subtract(everyItemCouponReduce)
                        .subtract(everyItemFullDiscountReduce));
                orderItemEntityVo.setTradeSn(tradeSN);
                orderItemEntityVo.setAfterSaleStatus(AfterSaleStatusEnum.NEW.name());
                orderItemEntityVo.setCommentStatus(CommentStatusEnum.NEW.name());
                orderItemEntityVo.setComplainStatus(ComplaintStatusEnum.NEW.name());
                orderItemList.add(orderItemEntityVo);
            }
            orderPriceDetailDto.setOriginalPrice(orderOriginalPrice);
            orderPriceDetailDto.setGoodsPrice(orderOriginalPrice);
            orderPriceDetailDto.setDiscountPrice(orderDiscountPrice);
            orderPriceDetailDto.setCouponPrice(orderCouponPrice);
            // 订单流水价格
            BigDecimal orderFlowPrice = orderOriginalPrice.subtract(orderDiscountPrice).subtract(orderCouponPrice);
            orderPriceDetailDto.setFlowPrice(orderFlowPrice);
            orderPriceDetailDto.setBillPrice(orderFlowPrice);
            orderPriceDetailDto.setTotalNum(orderTotalNum);
            // set总订单数据
            orderEntity.setDiscountPrice(priceDetailDTO.getDiscountPrice());
            orderEntity.setFlowPrice(orderFlowPrice);
            orderEntity.setFreightPrice(BigDecimal.ZERO);
            orderEntity.setGoodsNum(Integer.parseInt(orderTotalNum.toString()));
            orderEntity.setGoodsPrice(orderOriginalPrice);
            orderEntity.setPriceDetail(JSON.toJSONString(orderPriceDetailDto));// 价格详情直接把PriceDetailDto JSON化然后扔进去
            orderEntity.setUsePlatformMemberCouponId(usePlatformMemberCouponIds);
            orderEntity.setUseStoreMemberCouponIds(useStoreMemberCouponIds);
            orderEntity.setOrderPromotionType(OrderPromotionTypeEnum.NORMAL.name());
            // 保存订单 mq发送定时消息
            this.createOrder(orderEntity);
            //保存订单项 锁库存在订单服务远程调用那边
            orderItemService.createOrderItem(orderItemList);
            // 生成订单日志
            OrderLogEntity orderLogEntity = new OrderLogEntity();
            orderLogEntity.setCreateTime(ORDERCREATE);
            orderLogEntity.setMessage("订单[" + createOrderDto.getOrderSN() + "]创建");
            orderLogEntity.setOperatorId(0L);
            orderLogEntity.setOperatorName("系统");
            orderLogEntity.setOperatorType(CommunicationOwnerEnum.SYSTEM.description());
            orderLogEntity.setOrderSn(createOrderDto.getOrderSN());
            orderLogService.save(orderLogEntity);
        }

    }

    /**
     * 获取用户中心中的订单分页数据
     *
     * @param vo
     * @param params
     * @return
     */
    @Override
    public RespBean getBuyerOrderByPage(PageVO vo, OrderSearchParams params) {
        IPage<OrderSimpleVO> page = this.baseMapper.getBuyerOrderByPage(PageUtil.initPage(vo), params);

        return RespBean.success("获取成功", page);
    }

    /**
     * 获取订单详情
     *
     * @return
     */
    @Override
    public RespBean getOrderDetail(Map<String, Object> params) {
        String sn = MapUtil.getStr(params, "sn");
        Long id = MapUtil.getLong(params,"id");
        // 获取订单详情
        OrderDetailVO vo = new OrderDetailVO();
        OrderEntity orderEntity = new OrderEntity();
        if (id==null){
            orderEntity = this.getOne(new QueryWrapper<OrderEntity>().eq("sn",sn));
        }else {
            orderEntity = this.getById(id);
        }
        vo.setOrder(orderEntity);
        // 获取订单项
        List<OrderItemEntity> orderItemList = orderItemService.list(new QueryWrapper<OrderItemEntity>().eq("order_sn", sn));
        vo.setOrderItems(orderItemList);
        // 获取订单日志
        List<OrderLogEntity> orderLogList = orderLogService.list(new QueryWrapper<OrderLogEntity>().eq("order_sn", sn));
        vo.setOrderLogs(orderLogList);
        // 获取发票信息 （因为发票功能还未开发所以给先null）
        vo.setReceipt(new ReceiptEntity());
        vo.setOrderStatusValue(orderEntity.getOrderStatus());
        vo.setPayStatusValue(orderEntity.getPayStatus());
        vo.setDeliverStatusValue(orderEntity.getDeliverStatus());
        vo.setDeliveryMethodValue(orderEntity.getDeliveryMethod());
        vo.setPaymentMethodValue(orderEntity.getPaymentMethod());
        vo.setPriceDetail(orderEntity.getPriceDetail());

        return RespBean.success("获取成功", vo);
    }

    /**
     * 获取卖家端的订单分页数据
     *
     * @param vo
     * @param param
     * @return
     */
    @Override
    public RespBean getSellerOrderByPage(PageVO vo, SellerOrderSearchParam param) {
        IPage<OrderEntity> page = this.baseMapper.getSellerOrderByPage(PageUtil.initPage(vo), param, new Date());

        return RespBean.success("获取成功", page);
    }

    /**
     * 获取商城官方平台的订单分页数据
     *
     * @param vo
     * @param param
     * @return
     */
    @Override
    public RespBean getManagerOrderByPage(PageVO vo, ManagerOrderSearchParam param) {
        IPage<OrderEntity> page = this.baseMapper.getManagerOrderByPage(PageUtil.initPage(vo), param);

        return RespBean.success("获取成功", page);
    }

    /**
     * 修改订单价格
     *
     * @param params
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean updateOrderPrice(Map<String, Object> params) {
        String sn = MapUtil.getStr(params, "sn");
        BigDecimal updatePrice = MapUtil.get(params, "updatePrice", BigDecimal.class);
        Long storeId = MapUtil.getLong(params, "storeId");
        String storeName = MapUtil.getStr(params, "storeName");
        // 判定订单是否被支付
        OrderEntity order = getOrderBySn(sn);
        if (order.getPayStatus().equals(PayStatusEnum.PAID.description())) {
            return RespBean.error("已支付的订单不能修改金额");
        }
        PriceDetailDTO priceDetailDTO = order.getPriceDetailDTO();
        order.setUpdatePrice(updatePrice);
        priceDetailDTO.setUpdatePrice(updatePrice);
        priceDetailDTO.setFlowPrice(updatePrice);
        priceDetailDTO.setBillPrice(updatePrice);
        order.setFlowPrice(updatePrice);
        order.setPriceDetail(JSON.toJSONString(priceDetailDTO));
        // 保存
        boolean updateOrder = this.saveOrUpdate(order);

        // 修改交易价格
        boolean updateTrade = tradeService.update(new UpdateWrapper<TradeEntity>()
                .set("flow_price", updatePrice)
                .eq("sn", order.getTradeSn()));

        if (updateOrder && updateTrade) {
            // 增加订单日志
            OrderLogEntity orderLog = new OrderLogEntity();
            orderLog.setOrderSn(sn);
            orderLog.setMessage("订单[" + sn + "]修改订单价格为: " + updatePrice + " 元");
            orderLog.setOperatorId(storeId);
            orderLog.setOperatorName(storeName);
            if (storeId.equals(0l)) {
                orderLog.setOperatorType(UserEnums.MANAGER.name());
            } else {
                orderLog.setOperatorType(UserEnums.STORE.name());
            }
            orderLog.setCreateTime(new Date());
            orderLogService.save(orderLog);
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }

    }

    /**
     * 修改订单收货地址
     *
     * @param dto
     * @return
     */
    @Override
    public RespBean updateOrderConsignee(UpdateOrderConsigneeDto dto) {
        OrderEntity order = getOrderBySn(dto.getSn());
        // 生成日志
        OrderLogEntity orderLog = new OrderLogEntity();
        orderLog.setOrderSn(dto.getSn());
        String oldAddress = "收货人:" + order.getConsigneeName() + " 电话:" + order.getConsigneeMobile() + order.getConsigneeAddressPath() + " " + order.getConsigneeDetail();
        String newAddress = "收货人:" + dto.getConsigneeName() + " 电话:" + dto.getConsigneeMobile() + dto.getConsigneeAddressPath() + " " + dto.getConsigneeDetail();
        String message = "订单[" + dto.getSn() + "]收货信息修改，由[" + oldAddress + "]修改为[" + newAddress + "]";
        orderLog.setMessage(message);
        orderLog.setOperatorId(dto.getStoreId());
        orderLog.setOperatorName(dto.getStoreName());
        if (dto.getStoreId().equals(0l)) {
            orderLog.setOperatorType(UserEnums.MANAGER.name());
        } else {
            orderLog.setOperatorType(UserEnums.STORE.name());
        }
        orderLog.setCreateTime(new Date());
        orderLogService.save(orderLog);

        // 修改订单地址
        order.setConsigneeName(dto.getConsigneeName());
        order.setConsigneeMobile(dto.getConsigneeMobile());
        order.setConsigneeAddressPath(dto.getConsigneeAddressPath());
        order.setConsigneeAddressIdPath(dto.getConsigneeAddressIdPath());
        order.setConsigneeDetail(dto.getConsigneeDetail());

        boolean b = this.updateById(order);
        if (b) {
            return RespBean.success("修改地址成功");
        } else {
            return RespBean.error("修改地址失败");
        }

    }

    /**
     * 订单发货
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean orderDelivery(OrderDeliveryDto dto) {
        OrderEntity order = getOrderBySn(dto.getSn());
        // 增加订单日志
        OrderLogEntity orderLog = new OrderLogEntity();
        orderLog.setOrderSn(dto.getSn());
        orderLog.setMessage("订单["+dto.getSn()+"]发货,发货单号:["+dto.getLogisticsNo()+"]");
        orderLog.setOperatorId(dto.getStoreId());
        orderLog.setOperatorName(dto.getStoreName());
        orderLog.setOperatorType(UserEnums.STORE.name());
        orderLog.setCreateTime(new Date());
        orderLogService.save(orderLog);

        // 修改order信息
        // feign获取物流公司信息
        RespBean logisticsByIdResp = storeFeignService.getLogisticsById(dto.getLogisticsId());
        if (logisticsByIdResp.getObj()==null){
            return RespBean.error("物流错误");
        }
        LogisticsEntityDto logisticsEntity = JSON.parseObject(JSON.toJSONString(logisticsByIdResp.getObj()),LogisticsEntityDto.class);
        order.setLogisticsCode(logisticsEntity.getId());
        order.setLogisticsName(logisticsEntity.getName());
        order.setLogisticsNo(dto.getLogisticsNo());
        order.setLogisticsTime(new Date());
        order.setDeliverStatus(DeliverStatusEnum.DELIVERED.getDescription());
        order.setOrderStatus(OrderStatusEnum.DELIVERED.description());
        // 修改订单信息
        boolean updateOrder = this.updateById(order);
        // 修改订单项信息 货物可以进行售后、投诉
        boolean updateOrderItem = orderItemService.update(new UpdateWrapper<OrderItemEntity>().eq("order_sn", dto.getSn())
                .set("after_sale_status", OrderItemAfterSaleStatusEnum.NOT_APPLIED)
                .set("complain_status", OrderComplaintStatusEnum.NO_APPLY));
        // 解锁库存
        Map<String, Object> param = new HashMap<>();
        param.put("orderSN", order.getSn());
        RespBean respBean = wareFeignService.unLockStockWhenOrderPayed(param);
        boolean unLockStock = false;
        if (respBean.getCode() == 201) {
            unLockStock = true;
        }
        if(updateOrder && updateOrderItem && unLockStock){
            return RespBean.success("发货成功");
        }else {
            return RespBean.error("发货失败");
        }
    }

    /**
     * 获取物流信息
     * @param sn
     * @return
     */
    @Override
    public RespBean getTraces(String sn) {
        OrderEntity order = getOrderBySn(sn);
        TracesVo tracesVo = new TracesVo();

        tracesVo.setSn(sn);
        tracesVo.setLogisticsName(order.getLogisticsName());
        tracesVo.setLogisticsNo(order.getLogisticsNo());
        tracesVo.setTraces(null); // 此处先设置为null因为没有接入真实的快递系统
        return RespBean.success("获取成功",tracesVo);
    }

    /**
     * 官方管理平台取消订单
     * @param params
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean ManagerCancelOrder(Map<String, Object> params) {
        String sn = MapUtil.getStr(params, "sn");
        String reason = MapUtil.getStr(params, "reason"); // 取消订单的原因

        OrderEntity order = getOrderBySn(sn);
        if (CharSequenceUtil.equalsAny(order.getOrderStatus(),
                OrderStatusEnum.UNDELIVERED.description(),
                OrderStatusEnum.UNPAID.description(),
                OrderStatusEnum.PAID.description())) {
            // 如果订单在这几个类型之内
            order.setOrderStatus(OrderStatusEnum.CANCELLED.description());
            order.setCancelReason(reason);
            order.setPayStatus(PayStatusEnum.CANCEL.description());
            // 修改订单项
            List<OrderItemEntity> orderItemList = getOrderItem(sn);
            for (OrderItemEntity orderItem : orderItemList) {
                orderItem.setAfterSaleStatus(OrderItemAfterSaleStatusEnum.EXPIRED.name()); // 设置当前收货状态已失效
                orderItem.setComplainStatus(OrderComplaintStatusEnum.EXPIRED.name()); // 设置投诉状态已失效
            }
            // 生成日志
            OrderLogEntity orderLog = new OrderLogEntity();
            orderLog.setOrderSn(sn);
            orderLog.setMessage("订单["+sn+"]取消，原因:"+reason);
            orderLog.setCreateTime(new Date());
            orderLog.setOperatorType(UserEnums.MANAGER.name());
            orderLog.setOperatorId(0l);
            orderLog.setOperatorName("platform");
            // 修改订单
            boolean updateOrder = this.updateById(order);
            // 修改订单项
            boolean updateOrderItem = orderItemService.updateBatchById(orderItemList);
            // 保存日志
            orderLogService.save(orderLog);
            // 解锁库存
            Map<String, Object> unlockMap = new HashMap<>();
            unlockMap.put("orderSN", order.getSn());
            RespBean respBean = wareFeignService.unLockStockWhenOrderPayed(unlockMap);
            boolean unLockStock = false;
            if (respBean.getCode() == 201) {
                unLockStock = true;
            }
            if (updateOrder && updateOrderItem && unLockStock){
                return RespBean.success("取消成功");
            }else {
                return RespBean.error("取消失败");
            }
        }else {
            return RespBean.error("当前订单状态不能退款");
        }

    }

    /**
     * 用户取消订单
     * @param params
     * @return
     */
    @Transactional
    @Override
    public RespBean userCancelOrder(Map<String, Object> params) {
        String sn = MapUtil.getStr(params, "orderSn");
        String reason = MapUtil.getStr(params, "reason");
        if (CharSequenceUtil.isEmpty(reason)){
            return RespBean.error("订单取消原因不能为空");
        }
        Long memberId = MapUtil.getLong(params, "memberId");
        String username = MapUtil.getStr(params, "username");
        OrderEntity order = getOrderBySn(sn);
        if (CharSequenceUtil.equalsAny(order.getOrderStatus(),
                OrderStatusEnum.UNDELIVERED.description(),
                OrderStatusEnum.UNPAID.description(),
                OrderStatusEnum.PAID.description())) {
            // 如果订单在这几个类型之内
            order.setOrderStatus(OrderStatusEnum.CANCELLED.description());
            order.setCancelReason(reason);
            order.setPayStatus(PayStatusEnum.CANCEL.description());
            List<OrderItemEntity> orderItemList = getOrderItem(sn);
            for (OrderItemEntity orderItem : orderItemList) {
                orderItem.setAfterSaleStatus(OrderItemAfterSaleStatusEnum.EXPIRED.name()); // 设置当前收货状态已失效
                orderItem.setComplainStatus(OrderComplaintStatusEnum.EXPIRED.name()); // 设置投诉状态已失效
            }
            // 生成订单日志
            OrderLogEntity orderLog = new OrderLogEntity();
            orderLog.setOrderSn(sn);
            orderLog.setMessage("订单["+sn+"]取消，原因: 用户认为:"+reason);
            orderLog.setCreateTime(new Date());
            orderLog.setOperatorType(UserEnums.MEMBER.name());
            orderLog.setOperatorId(memberId);
            orderLog.setOperatorName(username);
            // 修改订单
            boolean updateOrder = this.updateById(order);
            // 修改订单项
            boolean updateOrderItem = orderItemService.updateBatchById(orderItemList);
            // 保存日志
            orderLogService.save(orderLog);
            // 解锁库存
            Map<String, Object> unlockMap = new HashMap<>();
            unlockMap.put("orderSN", order.getSn());
            RespBean respBean = wareFeignService.unLockStockWhenOrderPayed(unlockMap);
            boolean unLockStock = false;
            if (respBean.getCode() == 201) {
                unLockStock = true;
            }
            if (updateOrder && updateOrderItem && unLockStock){
                return RespBean.success("取消成功");
            }else {
                return RespBean.error("取消失败");
            }
        }else {
            return RespBean.error("当前订单状态不能退款");
        }

    }

    /**
     * 用户确认收货
     * @param params
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean userReceiveOrder(Map<String, Object> params) {
        String sn = MapUtil.getStr(params, "sn");
        Long memberId = MapUtil.getLong(params, "memberId");
        String username = MapUtil.getStr(params, "username");

        OrderEntity order = getOrderBySn(sn);
        if (order==null){
            return RespBean.error("订单不存在");
        }
        //判定是否是待收货状态
        if (!order.getOrderStatus().equals(OrderStatusEnum.DELIVERED.description())){
            return RespBean.error("订单状态错误，无法进行确认收货");
        }
        // 进行收货
        order.setOrderStatus(OrderStatusEnum.COMPLETED.description());
        order.setDeliverStatus(DeliverStatusEnum.RECEIVED.getDescription());
        order.setCompleteTime(new Date());

        // 收集订单项更改为可评论
        List<OrderItemEntity> orderItemList = orderItemService.list(new QueryWrapper<OrderItemEntity>().eq("order_sn", sn));
        if (orderItemList!=null){
            for (OrderItemEntity orderItem : orderItemList) {
                orderItem.setCommentStatus(CommentStatusEnum.UNFINISHED.name());
            }
        }

        OrderLogEntity orderLog = new OrderLogEntity();
        orderLog.setOrderSn(sn);
        orderLog.setCreateTime(new Date());
        String message = "订单[" + sn + "]买家收货";
        orderLog.setMessage(message);
        orderLog.setOperatorType(UserEnums.MEMBER.name());
        orderLog.setOperatorId(memberId);
        orderLog.setOperatorName(username);

        // 保存
        boolean updateOrder = this.updateById(order);
        boolean updateOrderItem = orderItemService.updateBatchById(orderItemList);
        boolean saveOrderLog = orderLogService.save(orderLog);
        if (updateOrder && saveOrderLog && updateOrderItem){
            return RespBean.success("订单收货成功");
        }else {
            return RespBean.error("订单收货失败");
        }
    }

    private List<OrderItemEntity> getOrderItem(String sn) {
        return orderItemService.list(new QueryWrapper<OrderItemEntity>().eq("order_sn",sn));
    }

    /**
     * 根据skuid获取memberCartEntityList里面对应的skuInfo
     *
     * @param memberCartEntityList
     * @param skuId
     */
    private MemberCartEntityVo getCartSkuItem(List<MemberCartEntityVo> memberCartEntityList, Long skuId) {
        MemberCartEntityVo vo = new MemberCartEntityVo();
        for (MemberCartEntityVo memberCartEntityVo : memberCartEntityList) {
            if (skuId.equals(memberCartEntityVo.getSkuId())) {
                return memberCartEntityVo;
            }
        }
        return vo;
    }

    public OrderEntity getOrderBySn(String sn) {
        return this.getOne(new QueryWrapper<OrderEntity>().eq("sn", sn));

    }

    public TradeEntity getTradeBySn(String tradeSn) {
        return tradeService.getOne(new QueryWrapper<TradeEntity>().eq("sn", tradeSn));
    }

}